Skip to main content
Version: 1.0.0

createProductDocument

Function Names: createOrUpdateProductDocument / createOrUpdateProductDocumentWithCatalogRef

Author: Domenico Cerone Creation Date: 25/09/2025
Last Reviewer: Domenico Cerone

Trigger: Called by populateVariantFromSku and populateVariantFromExcel

Purpose: Manages creation and updating of documents in the 'Products' Firestore collection from mapped JSON data and variant information. Handles the complete product lifecycle with automatic tag aggregation, brand management, and multi-language support.

Detailed Functionalityโ€‹

This component function handles the complete Products collection management with a sophisticated 3-step workflow for both new products and existing product updates. Includes thread-safe tag creation system with mutex synchronization to prevent duplicates in high-concurrency scenarios.

1. PRODUCT EXISTENCE CHECKโ€‹

  • Searches in 'Products' collection for document with modelName equal to glassesName
  • If EXISTS โ†’ updates fields and adds/updates variant in variants_map (STEP 3)
  • If NOT EXISTS โ†’ creates new complete product document (STEP 2)

2. NEW PRODUCT CREATIONโ€‹

  • Creates document with complete base structure
  • Populates fields from mapped JSON
  • Creates variants_map with current variant
  • Sets availableVariants = 0 (managed externally)
  • Uses Firestore auto-generated ID

3. EXISTING PRODUCT UPDATEโ€‹

  • Updates product fields from mapped JSON
  • Verifies if variant already exists in variants_map
  • If variant doesn't exist โ†’ adds new entry
  • If variant exists โ†’ updates existing entry
  • Updates availableVariants with real count
  • Updates list_frame_color_tags, list_size_tags, etc.

Fields Populated from Mapped JSONโ€‹

Base Product Fieldsโ€‹

  • modelName โ† glassesName (main identifier)
  • age โ† catAgeForGender
  • manufacturedProductStatus โ† manufacturedProductStatus
  • rxAble โ† rxAble (converted from "YES"/"NO" to boolean true/false)
  • mainBrandRef โ† Brand ID (find/create in MainBrands collection)

Image Fields (from current variant)โ€‹

  • imgUrl โ† poster
  • thumbnail โ† poster
  • urlImage โ† poster

Timestamp Fieldsโ€‹

  • lastUpdate โ† current timestamp (always updated, Date object)
  • productReleaseDate โ† productReleaseDate (if present in mapped JSON, Date object)
  • productEndDate โ† productEndDate (if present in mapped JSON, Date object)

Multi-language Descriptionsโ€‹

  • descriptionEn โ† description_en
  • descriptionIt โ† description_it
  • descriptionEs โ† description_es
  • descriptionFr โ† description_fr
  • descriptionDe โ† description_de

Tag Arrays (aggregated from all variants)โ€‹

  • list_frame_color_tags โ† [frameColor tag IDs from all product variants]
  • list_size_tags โ† [size tag IDs from all product variants]
  • list_line_tags โ† [line tag IDs]
  • list_tags โ† [catType, catAgeForGender, catGender, catForma, catMaterialOne, polarised, catLensesTreat, hingeType as tag IDs]

Variant Managementโ€‹

  • variants_map โ† array with entry for each product variant:
    • eanCode, id, publishedInARSLibrary (""), skuCode, upcCode, variantName (glassesName)
  • list_variants โ† [IDs of all product variants]
  • availableVariants โ† always 0 (logic managed externally)

Tag Aggregation Logicโ€‹

Tags are intelligently aggregated from all existing variants belonging to the same product:

Frame Color Tagsโ€‹

  • For each frameColor creates/finds document in Tags collection
  • Documents have: group="Frame Color", name="COLOR", type="frameColor"
  • IDs aggregated for all product variants

Size Tagsโ€‹

  • For each size creates/finds document in Tags collection
  • Documents have: group="Size", name="SIZE", type="size"
  • IDs aggregated for all product variants

Line Tagsโ€‹

  • For each line name creates/finds document in Tags collection
  • Documents have: catalogRef="BRAND_ID", group="Line", name="LINE", type="line"
  • ID used (unique per product since line name doesn't change between variants)

Category Tags (list_tags)โ€‹

Advanced tag system with automatic translations:

  • catType โ†’ Tag ID with: group="Tipologia", name=catType value, type="tag"
  • catAgeForGender โ†’ Tag ID with: group="Age For Gender", name=catAgeForGender value, type="categoria"
  • catGender โ†’ Tag ID with: group="Gender", name=translated catGender, type="categoria"
    • "WOMAN" โ†’ translated to "Donna"
    • "MAN" โ†’ translated to "Uomo"
    • Other values remain unchanged
  • catForma โ†’ Tag ID with: group="Forma", name=catForma value, type="tag"
  • catMaterialOne โ†’ Tag ID with: group="Materiale", name=catMaterialOne value, type="tag"
  • polarised โ†’ Tag ID based on value:
    • "YES" โ†’ group="Polarised", name="POLARIZED", type="tag"
    • "NO" โ†’ group="Polarised", name="NO POLARIZED", type="tag"
  • catLensesTreat โ†’ Tag ID with: group="Treatement", name=catLensesTreat value, type="tag"
  • hingeType โ†’ Tag ID with: group="Hinge Type", name=hingeType value, type="tag"

Brand Normalizationโ€‹

The mainBrandRef field is automatically normalized according to business rules:

  • Hugo brands: "HUGO" โ†’ "HUGO EYEWEAR"
  • Boss brands: "HUGO BOSS", "BOSS ORANGE" โ†’ "BOSS EYEWEAR"
  • Carrera brands: "CARRERA BY JIMMYCHOO", "CARRERA BIKE", "CARRERA SNOW", "CARRERA DUCATI" โ†’ "CARRERA"
  • Polaroid brands: "POLAROID ANCILLARIES", "POLAROID KIDS", "POLAROID STAYSAFE" โ†’ "POLAROID"
  • Smith brands: "SMITH FASHION & ACC.", "SMITH BIKE HELMETS", "SMITH SNOW", "SMITH BIKE GOGGLES", "PRIVATE LABEL SMITH", "SUNCLOUD" โ†’ "SMITH OPTICS"
  • Other brands remain unchanged

Variants Map Structureโ€‹

Each entry in variants_map contains:

  • eanCode โ† variant's eanCode (stored at variant level only)
  • id โ† variant document ID
  • publishedInARSLibrary โ† empty timestamp (future management)
  • skuCode โ† variant's skuModel
  • upcCode โ† variant's upcCode (stored at variant level only)
  • variantName โ† glassesName

Function Parametersโ€‹

createOrUpdateProductDocumentโ€‹

/**
* @param {Object} mappedJsonData - Mapped JSON data from populateVariantFromSku
* @param {string} variantDocumentId - ID of created/updated Variants document
* @param {string} requestId - Request ID for logging
* @returns {Promise<Object>} Operation result with details
*/

createOrUpdateProductDocumentWithCatalogRefโ€‹

/**
* @param {Object} mappedJsonData - Mapped JSON data from populateVariantFromSku
* @param {string} variantDocumentId - ID of created/updated Variants document
* @param {string} requestId - Request ID for logging
* @param {string} catalogOrderId - CatalogOrder ID (optional)
* @returns {Promise<Object>} Operation result with details
*/

Response Structureโ€‹

Success Responseโ€‹

{
"operation": "create",
"documentId": "auto_generated_product_id",
"modelName": "TOMMY HILFIGER TH 1950/G",
"variantsCount": 0,
"success": true,
"message": "New Products document created for model TOMMY HILFIGER TH 1950/G"
}

Error Responseโ€‹

{
"operation": "error",
"documentId": null,
"modelName": "TOMMY HILFIGER TH 1950/G",
"variantsCount": 0,
"success": false,
"message": "Error in Products document management: Missing glassesName",
"error": "Missing glassesName in mapped data - required for modelName"
}

Default Field Valuesโ€‹

All other fields maintain default values:

  • glassesCode: ""
  • glassesInclinationCoeff: ""
  • glassesInclinationCoeffIos: ""
  • glassesYCoeff: ""
  • glassesYCoeffAndroid: ""
  • glassesZCoeff: ""
  • glassesZCoeffAndroid: ""
  • logLoadingModel: ""
  • multiple3dViewerLink: ""
  • notesNumber: 0
  • priority: 0
  • status: "Incompleto"
  • urlProduct: ""
  • urlShadow: ""

Thread-Safe Tag Management Systemโ€‹

The function implements a sophisticated thread-safe tag creation system to prevent duplicate tags when processing multiple products simultaneously.

Tag Creation Functionsโ€‹

Brand Management:

  • findOrCreateMainBrand() - Thread-safe brand creation with normalization
  • Automatically normalizes brand names according to business rules
  • Prevents duplicate MainBrands documents in high-concurrency scenarios

Tag Creation (Thread-Safe):

  • findOrCreateFrameColorTag() - Frame color tags with group="Frame Color", type="frameColor" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateSizeTag() - Size tags with group="Size", type="size" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateLineTag() - Line tags with group="Line", type="line", catalogRef=brandId โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateCatTypeTag() - Category tags with group="Tipologia", type="tag" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateCatGenderTag() - Gender tags with group="Gender", type="categoria" (with translation: WOMANโ†’Donna, MANโ†’Uomo) โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateCatFormaTag() - Shape tags with group="Forma", type="tag" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateCatMaterialOneTag() - Material tags with group="Materiale", type="tag" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreatePolarisedTag() - Polarization tags with group="Polarised", type="tag" (YESโ†’POLARIZED, NOโ†’NO POLARIZED) โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateCatLensesTreatTag() - Lens treatment tags with group="Treatement", type="tag" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateHingeTypeTag() - Hinge type tags with group="Hinge Type", type="tag" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils
  • findOrCreateCatAgeForGenderTag() - Age for gender tags with group="Age For Gender", type="categoria" โ†’ Calls findOrCreateTagThreadSafe() from tagUtils

Mutex Synchronization Systemโ€‹

Problem Solved: When multiple products with the same tag values are processed in parallel, they could attempt to create the same Tags document simultaneously, leading to duplicates.

Solution: Thread-safe tag creation using findOrCreateTagThreadSafe():

  • Lock Acquisition: Before creating a tag, acquires exclusive lock using tag name + group + type as key
  • Lock Key Format: TAG_CREATE_{group}_{type}_{name}
  • Polling Mechanism: If lock is held, waits with exponential backoff (50ms โ†’ 1000ms max)
  • Automatic Cleanup: Expired locks (older than 10 minutes) are automatically cleaned up
  • Granular Locking: Each unique tag combination has its own lock
  • Error Safety: Locks are released in finally blocks to ensure cleanup

Benefits:

  • Prevents duplicate Tags documents
  • Maintains tag consistency across collections
  • Optimizes performance in batch processing scenarios
  • Provides automatic recovery from stuck locks